home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / rex.lha / rex / lib / Scanner.mi < prev    next >
Text File  |  1992-08-18  |  15KB  |  454 lines

  1. (* $Id: Scanner.mi,v 2.10 1992/08/18 09:05:32 grosch rel $ *)
  2.  
  3. $@ IMPLEMENTATION MODULE @;
  4.  
  5. $@ IMPORT SYSTEM, Checks, System, General, Positions, IO, DynArray, Strings, $Source;
  6. $G global user declarations
  7.  
  8. CONST
  9.    yyTabSpace        = 8;
  10.    yyDNoState        = 0;
  11.    yyFileStackSize    = 16;
  12.    yyInitBufferSize    = 1024 * 8 + 256;
  13. $C constant declarations
  14.  
  15. TYPE
  16.    yyTableElmt        = SHORTCARD;
  17.    yyStateRange        = yyTableElmt [0 .. yyDStateCount];
  18.    yyTableRange        = yyTableElmt [0 .. yyTableSize];
  19.    yyCombType        = RECORD Check, Next: yyStateRange; END;
  20.    yyCombTypePtr    = POINTER TO yyCombType;
  21.    yytChBufferPtr    = POINTER TO ARRAY [0 .. 1000000] OF CHAR;
  22.    yyChRange        = [yyFirstCh .. yyLastCh];
  23.  
  24. VAR
  25.    yyBasePtr        : ARRAY yyStateRange    OF LONGCARD    ;
  26.    yyDefault        : ARRAY yyStateRange    OF yyStateRange    ;
  27.    yyComb        : ARRAY yyTableRange    OF yyCombType    ;
  28.    yyEobTrans        : ARRAY yyStateRange    OF yyStateRange    ;
  29. $M yyAction        : ARRAY yyStateRange    OF yyTableElmt    ;
  30.    yyToLower, yyToUpper    : ARRAY yyChRange    OF CHAR        ;
  31.  
  32.    yyStateStack        : POINTER TO ARRAY [0 .. 1000000] OF yyStateRange;
  33.    yyStateStackSize    : LONGINT;
  34.    yyStartState        : yyStateRange;
  35.    yyPreviousStart    : yyStateRange;
  36.    yyCh            : CHAR;
  37.  
  38.    yySourceFile        : System.tFile;
  39.    yyEof        : BOOLEAN;
  40.    yyChBufferPtr    : yytChBufferPtr;
  41.    yyChBufferStart    : INTEGER;
  42.    yyChBufferSize    : LONGINT;
  43.    yyChBufferIndex    : INTEGER;
  44.    yyBytesRead        : INTEGER;
  45.    yyLineCount        : CARDINAL;
  46.    yyLineStart        : INTEGER;
  47.  
  48.    yyFileStackPtr    : SHORTCARD;
  49.    yyFileStack        : ARRAY [1 .. yyFileStackSize] OF RECORD
  50.                     SourceFile        : System.tFile;
  51.                  Eof        : BOOLEAN;
  52.                     ChBufferPtr    : yytChBufferPtr;
  53.                  ChBufferStart    : INTEGER;
  54.                  ChBufferSize    : LONGINT;
  55.                     ChBufferIndex    : INTEGER;
  56.                     BytesRead        : INTEGER;
  57.                     LineCount        : CARDINAL;
  58.                     LineStart        : INTEGER;
  59.               END;
  60.  
  61. PROCEDURE GetToken (): INTEGER;
  62.    VAR
  63.       yyState        : yyStateRange;
  64.       yyTablePtr    : yyCombTypePtr;
  65.       yyRestartFlag    : BOOLEAN;
  66.       yyi, yySource, yyTarget, yyChBufferFree    : INTEGER;
  67. $L local user declarations
  68. BEGIN
  69.    LOOP
  70.       yyState        := yyStartState;
  71.       TokenLength     := 0;
  72. $J    IF yyChBufferPtr^ [yyChBufferIndex - 1] = yyEolCh THEN INC (yyState); END;
  73.  
  74.       (* ASSERT yyChBuffer [yyChBufferIndex] = first character *)
  75.  
  76.       LOOP        (* eventually restart after sentinel *)
  77.      LOOP        (* execute as many state transitions as possible *)
  78.                             (* determine next state *)
  79.         yyTablePtr := yyCombTypePtr (yyBasePtr [yyState] +
  80.            ORD (yyChBufferPtr^ [yyChBufferIndex]) * SYSTEM.TSIZE (yyCombType));
  81.         IF yyTablePtr^.Check # yyState THEN
  82.            yyState := yyDefault [yyState];
  83.            IF yyState = yyDNoState THEN EXIT; END;
  84.         ELSE
  85.            yyState := yyTablePtr^.Next;
  86.            INC (TokenLength);
  87.            yyStateStack^ [TokenLength] := yyState;    (* push state *)
  88.            INC (yyChBufferIndex);        (* get next character *)
  89.         END;
  90.      END;
  91.  
  92.      LOOP                    (* search for last final state *)
  93. $A case header and user actions        (* CASE yyStateStack^ [TokenLength] OF *)
  94. $N non final states
  95.         (* non final states *)
  96.           DEC (yyChBufferIndex);    (* return character *)
  97.           DEC (TokenLength)        (* pop state *)
  98.  
  99. $P        |  yyDefaultState    : 
  100.           Attribute.Position.Line   := yyLineCount;
  101.           Attribute.Position.Column := yyChBufferIndex - yyLineStart;
  102.           INC (yyChBufferIndex);
  103.           TokenLength := 1;
  104. $D default action
  105.               yyRestartFlag := FALSE; EXIT;
  106.  
  107.         |  yyDNoState    :        (* automatic initialization *)
  108.           yyGetTables;
  109.           yyStateStack^ [0] := yyDefaultState; (* stack underflow sentinel *)
  110.           IF yyFileStackPtr = 0 THEN
  111.              yyInitialize;
  112.              yySourceFile := System.StdInput;
  113.           END;
  114.               yyRestartFlag := FALSE; EXIT;
  115.  
  116. $O        |  yyEobState    :        (* end of buffer sentinel found *)
  117.           DEC (yyChBufferIndex);    (* undo last state transition *)
  118.           DEC (TokenLength);        (* get previous state *)
  119.           IF TokenLength = 0 THEN
  120.              yyState := yyStartState;
  121. $J             IF yyChBufferPtr^ [yyChBufferIndex - 1] = yyEolCh THEN INC (yyState); END;
  122.           ELSE
  123.              yyState := yyStateStack^ [TokenLength];
  124.           END;
  125.  
  126.           IF yyChBufferIndex # yyChBufferStart + yyBytesRead THEN
  127.              yyState := yyEobTrans [yyState];    (* end of buffer sentinel in buffer *)
  128.              IF yyState # yyDNoState THEN
  129.             INC (yyChBufferIndex);
  130.             INC (TokenLength);
  131.             yyStateStack^ [TokenLength] := yyState;
  132.             yyRestartFlag := TRUE; EXIT;
  133.              END;
  134.           ELSE                (* end of buffer reached *)
  135.  
  136.              (* copy initial part of token in front of input buffer *)
  137.  
  138.              yySource := yyChBufferIndex - TokenLength - 1;
  139.              yyTarget := General.MaxAlign - TokenLength MOD General.MaxAlign - 1;
  140.              IF yySource # yyTarget THEN
  141.             FOR yyi := 1 TO TokenLength DO
  142.                yyChBufferPtr^ [yyTarget + yyi] := yyChBufferPtr^ [yySource + yyi];
  143.             END;
  144.             DEC (yyLineStart, yySource - yyTarget);
  145.             yyChBufferStart := yyTarget + TokenLength + 1;
  146.              ELSE
  147.             yyChBufferStart := yyChBufferIndex;
  148.              END;
  149.  
  150.              IF NOT yyEof THEN        (* read buffer and restart *)
  151.             yyChBufferFree := General.Exp2 (General.Log2 (yyChBufferSize - 4 - General.MaxAlign - TokenLength));
  152.             IF yyChBufferFree < yyChBufferSize DIV 8 THEN
  153.                DynArray.ExtendArray (yyChBufferPtr, yyChBufferSize, SYSTEM.TSIZE (CHAR));
  154.                IF yyChBufferPtr = NIL THEN yyErrorMessage (1); END;
  155.                yyChBufferFree := General.Exp2 (General.Log2 (yyChBufferSize - 4 - General.MaxAlign - TokenLength));
  156.                IF yyStateStackSize < yyChBufferSize THEN
  157.                   DynArray.ExtendArray (yyStateStack, yyStateStackSize, SYSTEM.TSIZE (yyStateRange));
  158.                   IF yyStateStack = NIL THEN yyErrorMessage (1); END;
  159.                END;
  160.             END;
  161.             yyChBufferIndex := yyChBufferStart;
  162. $@             yyBytesRead := $Source.GetLine (yySourceFile, SYSTEM.ADR
  163.                (yyChBufferPtr^ [yyChBufferIndex]), yyChBufferFree);
  164.             IF yyBytesRead <= 0 THEN yyBytesRead := 0; yyEof := TRUE; END;
  165.             yyChBufferPtr^ [yyChBufferStart + yyBytesRead    ] := yyEobCh;
  166.             yyChBufferPtr^ [yyChBufferStart + yyBytesRead + 1] := 0C;
  167.             yyRestartFlag := TRUE; EXIT;
  168.              END;
  169.  
  170.              IF TokenLength = 0 THEN    (* end of file reached *)
  171.             Attribute.Position.Line   := yyLineCount;
  172.             Attribute.Position.Column := yyChBufferIndex - yyLineStart;
  173.             CloseFile;
  174.             IF yyFileStackPtr = 0 THEN
  175. $E eof action
  176.             END;
  177.             IF yyFileStackPtr = 0 THEN RETURN EofToken; END;
  178.             yyRestartFlag := FALSE; EXIT;
  179.              END;
  180.           END;
  181.         ELSE
  182.            yyErrorMessage (0);
  183.         END;
  184.      END;
  185.      IF yyRestartFlag THEN ELSE EXIT; END;
  186.       END;
  187.    END;
  188.    END GetToken;
  189.  
  190. PROCEDURE BeginFile (FileName: ARRAY OF CHAR);
  191.    BEGIN
  192.       IF yyStateStack^ [0] = yyDNoState THEN    (* have tables been read in ? *)
  193.      yyGetTables;
  194.      yyStateStack^ [0] := yyDefaultState;    (* stack underflow sentinel *)
  195.       END;
  196.       yyInitialize;
  197. $@       yySourceFile := $Source.BeginSource (FileName);
  198.    END BeginFile;
  199.  
  200. PROCEDURE yyInitialize;
  201.    BEGIN
  202.       IF yyFileStackPtr >= yyFileStackSize THEN yyErrorMessage (3); END;
  203.       INC (yyFileStackPtr);            (* push file *)
  204.       WITH yyFileStack [yyFileStackPtr] DO
  205.      SourceFile    := yySourceFile        ;
  206.      Eof        := yyEof        ;
  207.      ChBufferPtr    := yyChBufferPtr    ;
  208.      ChBufferStart    := yyChBufferStart    ;
  209.      ChBufferSize    := yyChBufferSize    ;
  210.      ChBufferIndex    := yyChBufferIndex    ;
  211.      BytesRead    := yyBytesRead        ;
  212.      LineCount    := yyLineCount        ;
  213.      LineStart    := yyLineStart        ;
  214.       END;
  215.                         (* initialize file state *)
  216.       yyChBufferSize    := yyInitBufferSize;
  217.       DynArray.MakeArray (yyChBufferPtr, yyChBufferSize, SYSTEM.TSIZE (CHAR));
  218.       yyChBufferStart    := General.MaxAlign;
  219.       yyChBufferPtr^ [yyChBufferStart - 1] := yyEolCh; (* begin of line indicator *)
  220.       yyChBufferPtr^ [yyChBufferStart    ] := yyEobCh; (* end of buffer sentinel *)
  221.       yyChBufferPtr^ [yyChBufferStart + 1] := 0C;
  222.       yyChBufferIndex    := yyChBufferStart;
  223.       yyEof        := FALSE;
  224.       yyBytesRead    := 0;
  225.       yyLineCount    := 1;
  226.       yyLineStart    := yyChBufferStart - 1;
  227.    END yyInitialize;
  228.  
  229. PROCEDURE CloseFile;
  230.    BEGIN
  231.       IF yyFileStackPtr = 0 THEN yyErrorMessage (4); END;
  232. $@       $Source.CloseSource (yySourceFile);
  233.       DynArray.ReleaseArray (yyChBufferPtr, yyChBufferSize, SYSTEM.TSIZE (CHAR));
  234.       WITH yyFileStack [yyFileStackPtr] DO    (* pop file *)
  235.      yySourceFile    := SourceFile        ;
  236.      yyEof        := Eof            ;
  237.      yyChBufferPtr    := ChBufferPtr        ;
  238.      yyChBufferStart:= ChBufferStart    ;
  239.      yyChBufferSize    := ChBufferSize        ;
  240.      yyChBufferIndex:= ChBufferIndex    ;
  241.      yyBytesRead    := BytesRead        ;
  242.      yyLineCount    := LineCount        ;
  243.      yyLineStart    := LineStart        ;
  244.       END;
  245.       DEC (yyFileStackPtr);        
  246.    END CloseFile;
  247.  
  248. PROCEDURE GetWord (VAR Word: Strings.tString);
  249.    VAR i, WordStart    : INTEGER;
  250.    BEGIN
  251.       WordStart := yyChBufferIndex - TokenLength - 1;
  252.       FOR i := 1 TO TokenLength DO
  253.      Word.Chars [i] := yyChBufferPtr^ [WordStart + i];
  254.       END;
  255.       Word.Length := TokenLength;
  256.    END GetWord;
  257.  
  258. PROCEDURE GetLower (VAR Word: Strings.tString);
  259.    VAR i, WordStart    : INTEGER;
  260.    BEGIN
  261.       WordStart := yyChBufferIndex - TokenLength - 1;
  262.       FOR i := 1 TO TokenLength DO
  263.      Word.Chars [i] := yyToLower [yyChBufferPtr^ [WordStart + i]];
  264.       END;
  265.       Word.Length := TokenLength;
  266.    END GetLower;
  267.  
  268. PROCEDURE GetUpper (VAR Word: Strings.tString);
  269.    VAR i, WordStart    : INTEGER;
  270.    BEGIN
  271.       WordStart := yyChBufferIndex - TokenLength - 1;
  272.       FOR i := 1 TO TokenLength DO
  273.      Word.Chars [i] := yyToUpper [yyChBufferPtr^ [WordStart + i]];
  274.       END;
  275.       Word.Length := TokenLength;
  276.    END GetUpper;
  277.  
  278. PROCEDURE yyStart (State: yyStateRange);
  279.    BEGIN
  280.       yyPreviousStart    := yyStartState;
  281.       yyStartState    := State;
  282.    END yyStart;
  283.  
  284. PROCEDURE yyPrevious;
  285.    VAR s    : yyStateRange;
  286.    BEGIN
  287.       s              := yyStartState;
  288.       yyStartState    := yyPreviousStart;
  289.       yyPreviousStart := s;
  290.    END yyPrevious;
  291.  
  292. PROCEDURE yyEcho;
  293.    VAR i    : INTEGER;
  294.    BEGIN
  295.       FOR i := yyChBufferIndex - TokenLength TO yyChBufferIndex - 1 DO
  296.      IO.WriteC (IO.StdOutput, yyChBufferPtr^ [i]);
  297.       END;
  298.    END yyEcho;
  299.  
  300. PROCEDURE yyLess (n: INTEGER);
  301.    BEGIN
  302.       DEC (yyChBufferIndex, TokenLength - n);
  303.       TokenLength := n;
  304.    END yyLess;
  305.  
  306. PROCEDURE yyTab;
  307.    BEGIN
  308.       DEC (yyLineStart, yyTabSpace - 1 - (yyChBufferIndex - yyLineStart - 2) MOD yyTabSpace);
  309.    END yyTab;
  310.  
  311. PROCEDURE yyTab1 (a: INTEGER);
  312.    BEGIN
  313.       DEC (yyLineStart, yyTabSpace - 1 - (yyChBufferIndex - yyLineStart - TokenLength + a - 1) MOD yyTabSpace);
  314.    END yyTab1;
  315.  
  316. PROCEDURE yyTab2 (a, b: INTEGER);
  317.    BEGIN
  318.       DEC (yyLineStart, yyTabSpace - 1 - (yyChBufferIndex - yyLineStart - TokenLength + a - 1) MOD yyTabSpace);
  319.    END yyTab2;
  320.  
  321. PROCEDURE yyEol (Column: INTEGER);
  322.    BEGIN
  323.       INC (yyLineCount);
  324.       yyLineStart := yyChBufferIndex - 1 - Column;
  325.    END yyEol;
  326.  
  327. PROCEDURE output (c: CHAR);
  328.    BEGIN
  329.       IO.WriteC (IO.StdOutput, c);
  330.    END output;
  331.  
  332. PROCEDURE unput (c: CHAR);
  333.    BEGIN
  334.       DEC (yyChBufferIndex);
  335.       yyChBufferPtr^ [yyChBufferIndex] := c;
  336.    END unput;
  337.  
  338. PROCEDURE input (): CHAR;
  339.    BEGIN
  340.       IF yyChBufferIndex = yyChBufferStart + yyBytesRead THEN
  341.      IF NOT yyEof THEN
  342.         DEC (yyLineStart, yyBytesRead);
  343.         yyChBufferIndex := 0;
  344.         yyChBufferStart := 0;
  345. $@         yyBytesRead := $Source.GetLine (yySourceFile, yyChBufferPtr, General.Exp2 (General.Log2 (yyChBufferSize)));
  346.         IF yyBytesRead <= 0 THEN yyBytesRead := 0; yyEof := TRUE; END;
  347.         yyChBufferPtr^ [yyBytesRead    ] := yyEobCh;
  348.         yyChBufferPtr^ [yyBytesRead + 1] := 0C;
  349.      END;
  350.       END;
  351.       IF yyChBufferIndex = yyChBufferStart + yyBytesRead THEN
  352.      RETURN 0C;
  353.       ELSE
  354.      INC (yyChBufferIndex);
  355.      RETURN yyChBufferPtr^ [yyChBufferIndex - 1];
  356.       END
  357.    END input;
  358.  
  359. PROCEDURE BeginScanner;
  360.    BEGIN
  361. $I user initialization code
  362.    END BeginScanner;
  363.  
  364. PROCEDURE CloseScanner;
  365.    BEGIN
  366. $F user finalization code
  367.    END CloseScanner;
  368.  
  369. PROCEDURE yyGetTables;
  370.    VAR
  371.       BlockSize, j, n    : CARDINAL;
  372.       TableFile    : System.tFile;
  373.       i        : yyStateRange;
  374.       Base    : ARRAY yyStateRange OF yyTableRange;
  375.    BEGIN
  376.       BlockSize    := 64000 DIV SYSTEM.TSIZE (yyCombType);
  377.       TableFile := System.OpenInput (ScanTabName);
  378.       Checks.ErrorCheck ("yyGetTables.OpenInput", TableFile);
  379.       IF (yyGetTable (TableFile, SYSTEM.ADR (Base      )) DIV SYSTEM.TSIZE (yyTableElmt) - 1 # yyDStateCount) OR
  380.          (yyGetTable (TableFile, SYSTEM.ADR (yyDefault )) DIV SYSTEM.TSIZE (yyTableElmt) - 1 # yyDStateCount) OR
  381.          (yyGetTable (TableFile, SYSTEM.ADR (yyEobTrans)) DIV SYSTEM.TSIZE (yyTableElmt) - 1 # yyDStateCount)
  382. $M    OR (yyGetTable (TableFile, SYSTEM.ADR (yyAction  )) DIV SYSTEM.TSIZE (yyTableElmt) - 1 # yyDStateCount)
  383.      THEN
  384.      yyErrorMessage (2);
  385.       END;
  386.       n := 0;
  387.       j := 0;
  388.       WHILE j <= yyTableSize DO
  389.          INC (n, yyGetTable (TableFile, SYSTEM.ADR (yyComb [j])) DIV SYSTEM.TSIZE (yyCombType));
  390.          INC (j, BlockSize);
  391.       END;
  392.       IF n # yyTableSize + 1 THEN yyErrorMessage (2); END;
  393.       System.Close (TableFile);
  394.  
  395.       FOR i := 0 TO yyDStateCount DO
  396.      yyBasePtr [i] := LONGCARD (SYSTEM.ADR (yyComb [Base [i]]));
  397.       END;
  398.    END yyGetTables;
  399.  
  400. PROCEDURE yyGetTable (TableFile: System.tFile; Address: SYSTEM.ADDRESS): CARDINAL;
  401.    VAR
  402.       N        : INTEGER;
  403.       Length    : yyTableElmt;
  404.    BEGIN
  405.       N := System.Read (TableFile, SYSTEM.ADR (Length), SYSTEM.TSIZE (yyTableElmt));
  406.       Checks.ErrorCheck ("yyGetTable.Read1", N);
  407.       N := System.Read (TableFile, Address, Length);
  408.       Checks.ErrorCheck ("yyGetTable.Read2", N);
  409.       RETURN Length;
  410.    END yyGetTable;
  411.  
  412. PROCEDURE yyErrorMessage (ErrorCode: SHORTCARD);
  413.    BEGIN
  414.       Positions.WritePosition (IO.StdError, Attribute.Position);
  415.       CASE ErrorCode OF
  416. $@    | 0: IO.WriteS (IO.StdError, ": @: internal error");
  417. $@    | 1: IO.WriteS (IO.StdError, ": @: out of memory");
  418. $@    | 2: IO.WriteS (IO.StdError, ": @: table mismatch");
  419. $@    | 3: IO.WriteS (IO.StdError, ": @: too many nested include files");
  420. $@    | 4: IO.WriteS (IO.StdError, ": @: file stack underflow (too many calls of CloseFile)");
  421.       END;
  422.       IO.WriteNl (IO.StdError); Exit;
  423.    END yyErrorMessage;
  424.  
  425. PROCEDURE yyExit;
  426.    BEGIN
  427.       IO.CloseIO; System.Exit (1);
  428.    END yyExit;
  429.  
  430. BEGIN
  431. $@    ScanTabName        := "@.Tab";
  432.    Exit            := yyExit;
  433.    yyFileStackPtr    := 0;
  434.    yyStartState        := 1;            (* set up for auto init *)
  435.    yyPreviousStart    := 1;
  436.    yyBasePtr [yyStartState] := LONGCARD (SYSTEM.ADR (yyComb [0]));
  437.    yyDefault [yyStartState] := yyDNoState;
  438.    yyComb [0].Check    := yyDNoState;
  439.    yyChBufferPtr    := SYSTEM.ADR (yyComb [0]);    (* dirty trick *)
  440.    yyChBufferIndex    := 1;                (* dirty trick *)
  441.    yyStateStackSize    := yyInitBufferSize;
  442.    DynArray.MakeArray (yyStateStack, yyStateStackSize, SYSTEM.TSIZE (yyStateRange));
  443.    yyStateStack^ [0]    := yyDNoState;
  444.    
  445.    FOR yyCh := yyFirstCh TO yyLastCh DO yyToLower [yyCh] := yyCh; END;
  446.    yyToUpper := yyToLower;
  447.    FOR yyCh := 'A' TO 'Z' DO
  448.       yyToLower [yyCh] := CHR (ORD (yyCh) - ORD ('A') + ORD ('a'));
  449.    END;
  450.    FOR yyCh := 'a' TO 'z' DO
  451.       yyToUpper [yyCh] := CHR (ORD (yyCh) - ORD ('a') + ORD ('A'));
  452.    END;
  453. $@ END @.
  454.